//
//  IFlyIVWService.m
//  AIKITDemo
//
//  Created by xyzhang on 2023/3/8.
//

#import "IFlyIVWService.h"
#import "IFlyIVWRecordService.h"
#import "IFlyIVWStreamService.h"
#import "Definition.h"

//音频数据最大计数值
#define MAX_AUDIOQUEUE_COUNT_IVW 100

@interface IFlyIVWService ()<IFlyVoiceWakeupDelegate>
{
    int                          _keywordIndex;
}

@property (nonatomic, strong) AiHandle *handle;

@property (nonatomic, strong) NSOperationQueue *ivwOperationQueue;

@property (nonatomic, strong) IFlyIVWRecordService *ivwRecService;

@property (nonatomic, strong) IFlyIVWStreamService *ivwStreamService;

/// 唤醒词沙盒路径
@property (nonatomic, copy) NSString *wakeupWordsPath;

//@property (nonatomic, assign) int index;

/// 判断是否识别到唤醒词
@property (nonatomic, assign) BOOL isWoken;

@end

@implementation IFlyIVWService

+ (IFlyIVWService *)shareInstance {
    static IFlyIVWService  *instance = nil;
    static dispatch_once_t predict;
    dispatch_once(&predict, ^{
        instance = [[IFlyIVWService alloc] init];
    });
    return instance;
}

- (id)init {
    if (self = [super init]) {
        _isListening = NO;
        
        if (_ivwOperationQueue == nil) {
            _ivwOperationQueue = [[NSOperationQueue alloc] init];
        }
        
        _config = [IFlyIVWConfig sharedInstance];
        
    }
    return self;
}

- (void)initSDK:(NSDictionary*)args {
    NSString *APPID = args[@"APPID"];
    NSString *APIKEY = args[@"APIKEY"];
    NSString *APISECRET = args[@"APISECRET"];
    log(@"SDK初始化中...");
////    [AiHelper setConfig:@"host" value:@"http://aitest.iflyaicloud.com:8000"];
    int ret = [ILibrary initSDK:^(AiHelperMaker *maker) {
        maker.appId(APPID).apiKey(APIKEY).apiSecret(APISECRET).ability(AIKIT_ABILITYID_IVW);
    }];
    if (ret == 0) {
        log(@"SDK 初始化成功！");
    } else {
        log(@"SDK 初始化失败，ret: %d", ret);
        return;
    }

}


- (void)initEngine:(NSString *)abilityId {
    [super initEngine:abilityId];
    _abilityId = abilityId;
}

#pragma mark public

- (BOOL)startListening {
    [IFlyDebugLog showLog:@"%s [IN],_isListening =%d",__func__,self.isListening];
    
    @synchronized (self) {
        
        if(self.isListening){
            return NO;
        }
        
        if ([self isStreamSource]) {
            if (_ivwStreamService) {
                _ivwStreamService = nil;
            }
            
            _ivwStreamService = [[IFlyIVWStreamService alloc] initWithDelegate:self withConfig:_config];
            
            BOOL ret = [_ivwStreamService startListening];
            if (!ret) {
                return NO;
            }
            
            _isListening = YES;
            
//            [self wakeupByAudioStream];
        }else{
            
            if(_ivwRecService){
                _ivwRecService = nil;
            }
            
            _ivwRecService = [[IFlyIVWRecordService alloc] initWithDelegate:self withConfig:self.config];
            
            _isListening = YES;
            
            [_ivwOperationQueue addOperation:_ivwRecService];
            
        }
    }
    
    [IFlyDebugLog showLog:@"%s [OUT]",__func__];
    
    return YES;
}

- (BOOL)stopListening {
    [IFlyDebugLog showLog:@"%s [IN], isListening=%d", __func__, self.isListening];
    
    if(!self.isListening) {
        return NO;
    }
    
    if ([self isStreamSource]) {
        [self.ivwStreamService stopWrite];
//        [self.ivwStreamSession stopWrite];
    } else {
        if (_ivwOperationQueue.operationCount > 0) {
            for (IFlyIVWRecordService *op in _ivwOperationQueue.operations) {
                [op stopRecord];
            }
        }
    }
    
    [IFlyDebugLog showLog:@"%s[OUT]",__func__];
    return YES;
}

- (BOOL)cancel {
    [IFlyDebugLog showLog:@"%s",__func__];
    
    if (self.isListening) {
        
        BOOL flag = NO;
        
        if ([self isStreamSource]) {
            [self.ivwStreamService cancel];
        } else {
            if (_ivwOperationQueue.operationCount > 0){
                for (IFlyIVWRecordService *op in _ivwOperationQueue.operations) {
                    if (!op.isCancelled) {
                        //若当前线程在未执行状态之前cancel，将直接从线程队列移除并且不会进入main方法，以致不会回调onCompleted
                        if (op.state == IVWInit && op.isExecuting == NO) {
                            flag = YES;
                        }
                        [op cancel];
                    }
                }// for
            }
        } // if ([self isStreamSource])
        
        dispatch_async(dispatch_get_main_queue(), ^(){
           if (flag && [self.delegate respondsToSelector:@selector(onCompletedWithErrorCode:)]){
               [self.delegate onCompletedWithErrorCode:0];
           }
        });
    }
    
    return YES;
}

- (BOOL)writeAudio:(NSData *)audioData {

    [IFlyDebugLog showLog:@"%s [IN], _ivwStreamSession=%d, self.isListening=%d", __func__, _ivwStreamService, self.isListening];
    
    //确保对象存在，并且正在工作中
    if (!_ivwStreamService  && !self.isListening) {
        return NO;
    }
    
    return [_ivwStreamService writeAudio:audioData];
}

#pragma mark private

- (BOOL)isStreamSource {
    if ([self.config.audioSource isEqualToString:IFLY_AUDIO_SOURCE_STREAM]) {
        return YES;
    }
    return NO;
}

#pragma mark IFlyVoiceWakeupDelegate

- (void)onVolumeChanged:(NSUInteger)volume {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(onVolumeChanged:)]) {
            [self.delegate onVolumeChanged:volume];
        }
    });
}

- (void)onCompletedWithErrorCode:(int)errorCode {
    
    [IFlyDebugLog showLog:@"%s [IN] errorCode=%i", __func__, errorCode];
    
    @synchronized(self){
        _isListening = NO;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(onCompletedWithErrorCode:)]) {
            [self.delegate onCompletedWithErrorCode:errorCode];
        }
    });
    
    [IFlyDebugLog showLog:@"%s [OUT]", __func__];
}

- (void)onBeginOfSpeech {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(onBeginOfSpeech)]) {
            [self.delegate onBeginOfSpeech];
        }
    });
}

- (void)onEndOfSpeech {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(onEndOfSpeech)]) {
            [self.delegate onEndOfSpeech];
        }
    });
}

- (void)onResultStr:(NSString *)resultStr {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(onResultStr:)]) {
            [self.delegate onResultStr:resultStr];
        }
    });
}

@end
